package io.mft.runtime.config;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.mft.api.domain.Api;
import io.mft.api.domain.ApiRegulation;
import io.mft.api.domain.Regulation;
import io.mft.api.domain.RegulationProcessClassify;
import lombok.extern.slf4j.Slf4j;

/**
 * API信息加载器
 * 
 * @说明：TODO
 * @类型名称：ApiLoader
 * @创建者: 胡常建
 * @创建时间: 2021年1月26日 上午10:50:08
 * @修改者: 胡常建
 * @修改时间: 2021年1月26日 上午10:50:08
 */
@Slf4j
public abstract class ApiLoader implements ConfigLoader<List<Api>>{
	/**
	 * 加载所有的API
	 * 
	 * @说明: TODO
	 * @方法名称: load
	 * @参数 @return
	 * @返回类型 List<Api>
	 * @创建者: 胡常建
	 * @创建时间: 2021年1月26日 上午10:50:30
	 * @修改者: 胡常建
	 * @修改时间: 2021年1月26日 上午10:50:30
	 */
	public List<Api> load(String appid) {
		List<Api> apis = loadApi(appid);
		if (apis==null||apis.size()==0) {
			 log.warn("重要、重要、重要!!!!接口不存在，请检查API配置目录或者配置中心!!!!!!!!!!!!!!!!!!!!!");
			 log.warn("重要、重要、重要!!!!接口不存在，请检查API配置目录或者配置中心!!!!!!!!!!!!!!!!!!!!!");
			 log.warn("重要、重要、重要!!!!接口不存在，请检查API配置目录或者配置中心!!!!!!!!!!!!!!!!!!!!!");
		}
		apis.sort(new Comparator<Api>() {

			@Override
			public int compare(Api o1, Api o2) {
				return o1.getKey().compareTo(o2.getKey());
			}
		});
		return apis;
	}

	
	protected Api parseApi(ClassLoader pluginClassLoader,JSONObject jsonObject) {
		Api api=jsonObject.toBean(Api.class);
		JSONArray jsonArray=jsonObject.getJSONArray("apiRegulations");
		if (jsonArray!=null) {
			List<ApiRegulation> apiRegulations=new ArrayList<>();
			jsonArray.forEach(obj->{
				JSONObject json=(JSONObject)obj;
				JSONObject regulation=json.getJSONObject("regulation");
				String processClassify=regulation.getStr("processClassify");
				RegulationProcessClassify processClassifyType=RegulationProcessClassify.valueOf(processClassify);
				ApiRegulation apiRegulation=JSONUtil.toBean(json, ApiRegulation.class);
				
				Regulation regulationInstance=(Regulation)JSONUtil.toBean(regulation, processClassifyType.regulationClass());
				apiRegulation.setRegulation(regulationInstance);
				regulationInstance.setExecuteMode(processClassifyType.executeMode());
				JSONObject config=regulation.getJSONObject("config");
				if (ObjectUtil.isNotNull(config)) {
					regulationInstance.getConfig().putAll(config);
				}
				
				/**
				switch (processClassifyType) {
				case DataAccessProcessExecutor:
					DataAccessRegulation dataAccessRegulation=JSONUtil.toBean(regulation, DataAccessRegulation.class);
					apiRegulation.setRegulation(dataAccessRegulation);
					break;
				case LogicProcessExecutor:
					Regulation logicProcessExecutorRegulation=JSONUtil.toBean(regulation, Regulation.class);
					apiRegulation.setRegulation(logicProcessExecutorRegulation);
					break;
				case sync:
					Regulation syncRegulation=JSONUtil.toBean(regulation, Regulation.class);
					apiRegulation.setRegulation(syncRegulation);
					break;
				case async:
					Regulation asyncRegulation=JSONUtil.toBean(regulation, Regulation.class);
					apiRegulation.setRegulation(asyncRegulation);
					asyncRegulation.setExecuteMode(ExecuteMode.async);
					break;
				case syncWaitAsync:
					Regulation syncWaitAsyncRegulation=JSONUtil.toBean(regulation, Regulation.class);
					apiRegulation.setRegulation(syncWaitAsyncRegulation);
					syncWaitAsyncRegulation.setExecuteMode(ExecuteMode.syncWaitAsync);
					break;
				case flowPredictate:
					Regulation flowPredictateRegulation=JSONUtil.toBean(regulation, Regulation.class);
					apiRegulation.setRegulation(flowPredictateRegulation);
					flowPredictateRegulation.setExecuteMode(ExecuteMode.sync);
					break;						
				default:
					break;
				}**/
				apiRegulations.add(apiRegulation);
			});
			api.setApiRegulations(apiRegulations);
		}
		api.init();
		api.getApiRegulations().forEach(apiRegulation->{
			processApiRegulation(pluginClassLoader,api, apiRegulation);
		});
		return api;
	}
	
	protected void processApiRegulation(ClassLoader pluginClassLoader,Api api,ApiRegulation apoApiRegulation) {
	}
	protected abstract List<Api> loadApi(String appid);
}
